import { LibAppView } from "@/lib";
import { App, Button, Card, Form } from "antd";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
import 'react-quill/dist/quill.snow.css';
import { queueCallRaceAll, queueCallFunc, utils } from "elmer-common";
import { IEditField, Fields } from "./Fields";
import { AdminRight, useAdminRight } from "@/pages/Admin/data/AdminPageAuth";


type BeforeHook = (option: Omit<LibAppView.IWithServiceApi, "responseData"> & { data: any; }) => Promise<any>;
interface IBeforeHook {
    name: string;
    callback: BeforeHook;
}

interface IActionButton {
    label: string|React.ReactNode;
    type?: string;
    onClick: (data: any, defaultData: any) => void;
    props?: any;
}

interface IResourceEditProps {
    beforeHook?: IBeforeHook[];
    beforeHookCallMode?: 'QueueCall'|'RaceCall';
    afterSubmit?: (data: any) => void;
    buildRequest?: Function;
    buildResponse?: Function;
    submitEndPoint: string;
    fields: IEditField[];
    initValues?: any;
    minHeight?: string;
    submitText?: string;
    backText?: string;
    backHidden?: boolean;
    successMessage?: string;
    labelCol?: number;
    wrapperCol?: number;
    onSubmitSuccess?: (data: any) => void;
    overrideRight?: boolean;
    actionButtons?: IActionButton[];
    hideSubmit?: boolean;
    reviewRight?: boolean;
    overrideSubmit?: boolean;
    onSubmit?: (data: any) => void;
}

const mergeFormData = (defaultValues: any, formData: any) => {
    const result = {...defaultValues};
    Object.keys(formData).forEach((key: string) => {
        if(null !== formData[key] && undefined !== formData[key]) {
            result[key] = formData[key];
        }
    });
    return result;
};

export const createFields = (fields: IEditField[]) => {
    return fields.map((item) => {
        return {...item};
    });
};

const EditResource = LibAppView.withService<IResourceEditProps>({
    loadingOptions: {
        defaultVisible: true,
        "mountWithLoading": true,
        "controlled": true
    }
})((props) => {
    const app = LibAppView.useApp();
    const microApp = LibAppView.useMicroApp();
    const antApp = App.useApp();
    const intl = useIntl();
    const journeyData = LibAppView.useJourneyData();
    const editData = journeyData.currentStepState || {};
    const hasEditRight = !props.overrideRight ? useAdminRight("editable") : true;
    const [ beforeHookData, setBeforeHookData ] = useState({});
    const [ form ] = Form.useForm();
    const [ componentDisabled, setComponentDisabled] = useState((!hasEditRight && !props.overrideRight) || props.reviewRight);
    
    
    const defaultFormData = useMemo(() => {
        const formData = {
            ...(props.initValues || {}),
            ...editData,
            status: editData.status
        };
        return typeof props.buildResponse === "function" ? props.buildResponse(formData) : formData;
    }, []);
    const onSubmit = useCallback(() => {
        const formData = form.getFieldsValue();
        const onSubmitSuccess = () => {
            setComponentDisabled(false);
            antApp.message.success(
                props.successMessage || intl.formatMessage({ id: "admin.pages.form.submit.success", defaultMessage: "Submit successfully."}),
                2
            );
            if(typeof props.onSubmitSuccess === "function") {
                props.onSubmitSuccess({});
            } else {
                microApp.goBack();
            }
        };
        form.validateFields().then(() => {
            const requestData = typeof props.buildRequest === "function" ? props.buildRequest({
                ...defaultFormData,
                ...formData
            }, defaultFormData) : formData;
             
            setComponentDisabled(true);
            app.serviceApi.send({
                endPoint: props.submitEndPoint,
                data: requestData
            }).then(() => {
                if(typeof props.afterSubmit === "function") {
                    utils.invoke(props.afterSubmit, {
                        ...defaultFormData,
                        ...requestData
                    }).then(() => {
                        onSubmitSuccess();
                    }).catch((err) => {
                        setComponentDisabled(false);
                        antApp.message.error(err.message || "提交数据失败，请重试。");
                    });
                } else {
                    onSubmitSuccess();
                }
                
            }).catch((err) => {
                setComponentDisabled(false);
                antApp.message.error(err.message);
            });
        }).catch((err) => {
            antApp.message.error(err.message || intl.formatMessage({
                id: "admin.pages.article.formItem.required",
                defaultMessage: "Please enter the article title."
            }));
        });
    }, [form, defaultFormData, props.buildRequest]);

    const formItemFiels = useMemo(() => {
        return props.fields.map((item) => {
            const rules = item.rules || [];
            return {
                ...item,
                rules: rules.length > 0 ? rules.map((item) => {
                    if(typeof (item as any).validator === "function") {
                        return {
                            ...item,
                            validator: (...args: any[]) => {
                                return (item as any).validator(...args, form);
                            }
                        };
                    } else {
                        return {
                            ...item
                        };
                    }
                }) : null
            }
        })
    }, [props.fields, form]);

    const overrideNextProps = useMemo(() => {
        return props.overrideRight ? { disabled: false } : {}
    }, [props.overrideRight]);

    useEffect(() => {
        const hookCallMode = props.beforeHookCallMode || "RaceCall";
        if(props.beforeHook && props.beforeHook.length > 0) {
            const hookCallParams = props.beforeHook.map((hook) => {
                return {
                    id: hook.name,
                    fn: (res: any) => {
                        return hook.callback({
                            "withLoadingApi": props.withLoadingApi,
                            "withServiceApi": props.withServiceApi,
                            data: res.result
                        })
                    }
                };
            });
            const listCallFunc = hookCallMode === "QueueCall" ? queueCallFunc : queueCallRaceAll;
            if(hookCallMode === "QueueCall") {
                listCallFunc(hookCallParams).then((data: any) => {
                    setBeforeHookData(data);
                    props.withLoadingApi.hide();
                }).catch((err) => {
                    console.error(err);
                    antApp.message.error(err.message);
                });
            }
        } else {
            props.withLoadingApi.hide();
        }
    }, []);

    return (
        <Card style={{ width: "100%", minHeight: props.minHeight || "76vh", padding: 20 }}>
        <Form
            labelCol={{ span: props.labelCol || 5 }}
            wrapperCol={{ span: props.wrapperCol || 12 }}
            layout="horizontal"
            disabled={componentDisabled}
            form={form}
            initialValues={defaultFormData}
        >
            <Fields form={form} fields={formItemFiels as any[]} disabled={componentDisabled} data={beforeHookData} />
            <Form.Item wrapperCol={{ offset: 5, span: 16 }}>
                {
                    !props.hideSubmit && <AdminRight authRight="editable" mode="disabled" nextProps={overrideNextProps}>
                        <Button loading={ hasEditRight && componentDisabled} style={{marginLeft: 0}} type="primary" htmlType="submit" onClick={onSubmit}>
                            { props.submitText ? props.submitText : <FormattedMessage id="admin.pages.form.submit" />}
                        </Button>
                    </AdminRight>
                }
                { props.actionButtons && <>{props.actionButtons.map((btn) => {
                    return <Button style={{marginLeft: 10}} type={btn.type || "default"} {...(btn.props||{})} onClick={() => {
                        form.validateFields().then(() => {
                            const formData = form.getFieldsValue();
                            const requestData = typeof props.buildRequest === "function" ? props.buildRequest({
                                ...defaultFormData,
                                ...formData
                            }, defaultFormData) : formData;
                            setComponentDisabled(true);
                            utils.invoke(btn.onClick, requestData, defaultFormData).then(() => {
                                setComponentDisabled(false);
                            }).catch((err) => {
                                antApp.message.error(err.message || "操作失败，未知错误");
                                setComponentDisabled(false);
                            });
                        }).catch(() => {
                            antApp.message.error(intl.formatMessage({
                                id: "admin.pages.article.formItem.required",
                                defaultMessage: "Please enter the article title."
                            }));
                        });
                    }}>
                        { btn.label }
                    </Button>
                })}</>}
                { !props.backHidden && <Button disabled={false} style={{marginLeft: 10}} type="default" onClick={() => {
                    microApp.goBack();
                }}>
                    { props.backText || <FormattedMessage id="admin.pages.form.back" /> }
                </Button> }
            </Form.Item>
        </Form>
    </Card>
    );
});

export default EditResource;
